import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Iterator;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import jess.Fact;
import jess.JessException;
import jess.Rete;

public class TrafficGui extends JFrame {

    // GUI Stuff
    Container container;
    Cursor c;
    Icon building = new ImageIcon("citybuilding.PNG");
    Icon carsWest = new ImageIcon("cars.PNG");
    Icon carsNorth = new ImageIcon("carsNorth.PNG");
    Icon carsEast = new ImageIcon("carsEast.PNG");
    Icon carsSouth = new ImageIcon("carsSouth.PNG");
    Icon lightNS = new ImageIcon("lightNS.png");
    Icon lightEW = new ImageIcon("lightEW.png");
    Icon accident = new ImageIcon("accident.jpg");
    Icon lastIcon;
    Image emergencyIcon;
    MyMouseAdapter mouse = new MyMouseAdapter();
    MyMouseAdapter2 mouse2 = new MyMouseAdapter2();
    JButton current;
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    JComboBox WWalk;
    JComboBox EWalk;
    JTextField response = new JTextField("Response will appear here.", 50);
    static final long serialVersionUID = 123;

    // Variable Stuff
    JButton[][] buttonHolder = new JButton[3][6];
    boolean emergency1 = false;
    boolean emergency = false;
    int emergencyLocation1 = 0;
    public boolean WEWwalk = false;
    public boolean WNSwalk = false;
    public boolean EEWwalk = false;
    public boolean ENSwalk = false;
    public boolean backup = false;
    public int[] emergencyLocation = { -1, -1 };
    public String emergencyArea = "none";
    public String WNcars, WWcars, WEcars, WScars;
    public String ENcars, EWcars, EEcars, EScars;
    public String WLightDirection, ELightDirection;

    TrafficGui() {
        container = getContentPane();
        container.setLayout(new BorderLayout());
        response.setEditable(false);

        JPanel board = new JPanel();
        JLabel westLabel = new JLabel("West Walk Requests?");
        JLabel eastLabel = new JLabel("East Walk Requests?");
        String[] options = { "", "NS", "EW", "NS/EW" };
        WWalk = new JComboBox(options);
        EWalk = new JComboBox(options);

        JButton ask = new JButton("ASK!");
        ask.setBackground(Color.green);
        ask.setForeground(Color.white);
        ask.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                extractVariables();
                System.out.println(WNcars);
        		container.setCursor(Cursor.getDefaultCursor());
                // call the JESS Engine and presumably return a string
                response.setFont(new Font("serif", Font.BOLD, 12));
                response.setText(runJess());
                emergency1 = false;
            }
        });

        JButton emerg = new JButton("EMERGENCY!");
        emerg.setBackground(Color.red);
        emerg.setForeground(Color.white);
        emerg.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (emergency1 == false) {
                    emergency1 = true;
                    emergencyIcon = toolkit.getImage("emergency.png");
                    c = toolkit.createCustomCursor(emergencyIcon, new Point(container.getX(), container.getY()), "img");
                    container.setCursor(c);
                }
            }
        });

        JButton reset = new JButton("RESET");
        reset.setBackground(Color.blue);
        reset.setForeground(Color.white);
        reset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                reset(false);
                container.setCursor(Cursor.getDefaultCursor());
            }
        });

        response.setFont(new Font("times", Font.ITALIC, 12));

        board.add(westLabel);
        board.add(WWalk);
        board.add(ask);
        board.add(emerg);
        board.add(reset);
        board.add(EWalk);
        board.add(eastLabel);
        container.add(board, BorderLayout.NORTH);
        container.add(response, BorderLayout.SOUTH);

        JPanel grid = new JPanel();
        grid.setLayout(new GridLayout(3, 6));
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 6; j++) {
                if (i == 0) {
                    if (j == 1 || j == 4) {
                        JButton button = new JButton("0", carsNorth);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        button.addMouseListener(mouse);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    } else {
                        JButton button = new JButton(building);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    }
                } else if (i == 1) {
                    if (j == 0 || j == 3) {
                        JButton button = new JButton("0", carsWest);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        button.setVerticalAlignment(JButton.CENTER);
                        button.addMouseListener(mouse);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    } else if (j == 2 || j == 5) {
                        JButton button = new JButton("0", carsEast);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        button.setVerticalAlignment(JButton.CENTER);
                        button.addMouseListener(mouse);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    } else {
                        JButton button = new JButton(lightNS);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        button.addMouseListener(mouse2);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    }
                } else {
                    if (j == 1 || j == 4) {
                        JButton button = new JButton("0", carsSouth);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        button.addMouseListener(mouse);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    } else {
                        JButton button = new JButton(building);
                        button.setHorizontalTextPosition(JButton.CENTER);
                        grid.add(button);
                        buttonHolder[i][j] = button;
                    }
                }
            }
        }
        buttonHolder[1][4].setIcon(lightEW);

        container.add(grid, BorderLayout.CENTER);
        setSize(905, 500);
        setLocation(300, 100);
        setVisible(true);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    class MyMouseAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            if (emergency1 == false) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    JButton button = (JButton) e.getSource();
                    if (button.getText().equals("!")) {
                        button.setText("0");
                    } else {
                        int number = Integer.parseInt(button.getText());
                        number++;
                        button.setText((number + ""));
                    }
                } else {
                    JButton button = (JButton) e.getSource();
                    int number = Integer.parseInt(button.getText());
                    if (number > 0)
                        number--;
                    button.doClick();
                    button.setText((number + ""));

                }
            } else {
                JButton button = (JButton) e.getSource();
                if (emergencyLocation1 != 0 && lastIcon == null)
                    current.setText("0");
                if (lastIcon != null) {
                    current.setIcon(lastIcon);
                }
                lastIcon = button.getIcon();
                button.setIcon(accident);
                emergencyLocation1 = 1;
                container.setCursor(Cursor.getDefaultCursor());
                current = button;
                emergency1 = false;
            }
        }
    }

    class MyMouseAdapter2 extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            if (emergency1 == false) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    JButton button = (JButton) e.getSource();
                    Icon switchMe = button.getIcon();
                    String lightName = switchMe.toString();
                    if (lightName.equals("lightNS.png")) {
                        button.setIcon(lightEW);
                        repaint();
                    } else {
                        button.setIcon(lightNS);
                        repaint();
                    }
                }
            } else {
                JButton button = (JButton) e.getSource();
                if (emergencyLocation1 != 0 && lastIcon == null)
                    current.setText("0");
                if (lastIcon != null) {
                    current.setIcon(lastIcon);
                }
                lastIcon = button.getIcon();
                button.setIcon(accident);
                emergencyLocation1 = 1;
                container.setCursor(Cursor.getDefaultCursor());
                current = button;
                emergency1 = false;
            }
        }

    }

    public void reset(boolean leaveResponse) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 6; j++) {
                JButton button = buttonHolder[i][j];
                if (i == 0) {
                    if (j == 1 || j == 4) {
                        button.setText("0");
                        button.setIcon(carsNorth);
                    }
                } else if (i == 1) {
                    if (j == 0 || j == 3) {
                        button.setText("0");
                        button.setIcon(carsWest);
                    } else if (j == 2 || j == 5) {
                        button.setText("0");
                        button.setIcon(carsEast);
                    } else {
                        button.setIcon(lightNS);
                    }
                } else {
                    if (j == 1 || j == 4) {
                        button.setText("0");
                        button.setIcon(carsSouth);
                    }
                }
            }
        }
        buttonHolder[1][4].setIcon(lightEW);
        WWalk.setSelectedIndex(0);
        EWalk.setSelectedIndex(0);
        WEWwalk = false;
        WNSwalk = false;
        EEWwalk = false;
        ENSwalk = false;
        emergencyLocation[0] = -1;
        emergencyLocation[1] = -1;
        emergencyArea = "none";
        emergency1 = false;
        emergency = false;
        WLightDirection = "NS";
        ELightDirection = "EW";
        WNcars = "";
        WWcars = "";
        WEcars = "";
        WScars = "";
        ENcars = "";
        EWcars = "";
        EEcars = "";
        EScars = "";

        if (!leaveResponse) {
            response.setFont(new Font("sans", Font.ITALIC, 12));
            response.setText("Response will appear here.");
        }
    }

    public void extractVariables() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 6; j++) {
                JButton myButton = buttonHolder[i][j];
                if (i == 0) {
                    if (j == 1) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "WN";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            WNcars = "wn-heavy";
                        } else {
                            WNcars = "wn-light";
                        }
                    } else if (j == 4) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "EN";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            ENcars = "en-heavy";
                        } else {
                            ENcars = "en-light";
                        }
                    }
                } else if (i == 1) {
                    if (j == 0) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "WW";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            WWcars = "ww-heavy";
                        } else {
                            WWcars = "ww-light";
                        }
                    } else if (j == 1) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "W";
                            emergency = true;
                        }
                        if (myButton.getIcon().toString().equals("lightNS.png")) {
                            WLightDirection = "NS";
                        } else {
                            WLightDirection = "EW";
                        }

                    } else if (j == 2) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "M";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            WEcars = "we-heavy";
                        } else {
                            WEcars = "we-light";
                        }
                    } else if (j == 3) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "M";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            EWcars = "ew-heavy";
                        } else {
                            EWcars = "ew-light";
                        }
                    } else if (j == 4) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "E";
                            emergency = true;
                        }
                        if (myButton.getIcon().toString().equals("lightNS.png")) {
                            ELightDirection = "NS";
                        } else {
                            ELightDirection = "EW";
                        }
                    } else if (j == 5) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "EE";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            EEcars = "ee-heavy";
                        } else {
                            EEcars = "ee-light";
                        }
                    }
                } else if (i == 2) {
                    if (j == 1) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "WS";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            WScars = "ws-heavy";
                        } else {
                            WScars = "ws-light";
                        }
                    } else if (j == 4) {
                        if (myButton.getIcon().toString().equals("accident.jpg")) {
                            emergencyArea = "ES";
                            emergency = true;
                        }
                        if (Integer.parseInt(myButton.getText()) >= 5) {
                            EScars = "es-heavy";
                        } else {
                            EScars = "es-light";
                        }
                    }
                }
            }
        }
        String walkValue = WWalk.getSelectedItem().toString();
        if (walkValue.equals("NS")) {
            WNSwalk = true;
        }
        if (walkValue.equals("EW")) {
            WEWwalk = true;
        }
        if (walkValue.equals("NS/EW")) {
            WNSwalk = true;
            WEWwalk = true;
        }
        walkValue = EWalk.getSelectedItem().toString();
        if (walkValue.equals("NS")) {
            ENSwalk = true;
        }
        if (walkValue.equals("EW")) {
            EEWwalk = true;
        }
        if (walkValue.equals("NS/EW")) {
            ENSwalk = true;
            EEWwalk = true;
        }
        // System.out.println(emergencyArea);
    }

    public static void main(String[] args) {
        new TrafficGui();
    }

    public String runJess() {

        Rete rete = new Rete();
        try {

            rete.executeCommand("(batch rules.clp)");

            rete.executeCommand("(assert (" + WNcars + "))");
            rete.executeCommand("(assert (" + WWcars + "))");
            rete.executeCommand("(assert (" + WScars + "))");
            rete.executeCommand("(assert (" + WEcars + "))");

            rete.executeCommand("(assert (" + ENcars + "))");
            rete.executeCommand("(assert (" + EWcars + "))");
            rete.executeCommand("(assert (" + EScars + "))");
            rete.executeCommand("(assert (" + EEcars + "))");

            if (WEWwalk) {
                rete.executeCommand("(assert (PWEW))");
            }

            if (WNSwalk) {
                rete.executeCommand("(assert (PWNS))");
            }

            if (EEWwalk) {
                rete.executeCommand("(assert (PEEW))");
            }

            if (ENSwalk) {
                rete.executeCommand("(assert (PENS))");
            }

            if (emergency) {

                rete.executeCommand("(assert (emergency " + emergencyArea + "))");
                if (emergencyArea.charAt(0) == 'W') {
                    rete.executeCommand("(assert (no-e-emergency))");
                    rete.executeCommand("(assert (w-emergency))");
                } else if (emergencyArea.charAt(0) == 'E') {
                    rete.executeCommand("(assert (no-w-emergency))");
                    rete.executeCommand("(assert (e-emergency))");
                } else {
                }

            } else {
                rete.executeCommand("(assert (no-w-emergency))");
                rete.executeCommand("(assert (no-e-emergency))");
            }

            rete.executeCommand("(assert (LW" + WLightDirection + "))");
            rete.executeCommand("(assert (LE" + ELightDirection + "))");

            if (backup) {
                rete.executeCommand("(assert (backup))");
            }

            if (emergency) {
                rete.executeCommand("(assert (emergency))");
                rete.executeCommand("(bind ?el \"" + emergencyLocation + "\" )");
            }

            // System.out.println("\nOutput: ");

            rete.run();

            @SuppressWarnings("unchecked")
            Iterator<Fact> facts = rete.listFacts();

            String west = new String();
            String east = new String();
            boolean westWalk = false;
            boolean eastWalk = false;

            while (facts.hasNext()) {
                Fact fact = facts.next();
                // System.out.println(fact);
                if (fact.toString().contains("west-traffic-light")) {
                    west = fact.toString().replace("MAIN::west-traffic-light ", "").replace("(", "").replace(")", "");
                }

                if (fact.toString().contains("east-traffic-light")) {
                    east = fact.toString().replace("MAIN::east-traffic-light ", "").replace("(", "").replace(")", "");
                }

                if (fact.toString().contains("w-pause-continue")) {
                    westWalk = true;
                }

                if (fact.toString().contains("e-pause-continue")) {
                    eastWalk = true;
                }

            }

            String westString = "West Intersection: ";
            if (westWalk) {
                westString += "Pause for pedestrians between light change.";
            }

            if (west.equals("normal")) {
                westString += "Continue normal operation";
            } else if (west.equals("change")) {
                westString += "Change light immediately";
            } else if (west.equals("extend")) {
                westString += "Extend light duration";
            } else if (west.equals("shorten")) {
                westString += "Shorten light duration";
            } else if (west.equals("terminate")) {
                westString += "Change light to blinking red";
            }

            String eastString = "East Intersection: ";
            if (eastWalk) {
                eastString += "Pause for pedestrians between light change. ";
            }
            if (east.equals("normal")) {
                eastString += "Continue normal operation";
            } else if (east.equals("change")) {
                eastString += "Change light immediately";
            } else if (east.equals("extend")) {
                eastString += "Extend light duration";
            } else if (east.equals("shorten")) {
                eastString += "Shorten light duration";
            } else if (east.equals("terminate")) {
                eastString += "Change light to blinking red";
            }

            // System.out.println(westString);
            // System.out.println(eastString);

            return (westString + " " + eastString);

        } catch (JessException e) {
            e.printStackTrace();
        }
        return null;
    }

}
